using BootstrapBlazorApp.Server.LLMs.function;
using BootstrapBlazorApp.Server.LLMs.function.Kimi;
using BootstrapBlazorApp.Server.LLMs.messages;
using Newtonsoft.Json;
using System.Reflection;
using ArgDescription = BootstrapBlazorApp.Server.LLMs.function.Kimi.ArgDescription;
using Function = BootstrapBlazorApp.Server.LLMs.function.Kimi.Function;
using Parameters = BootstrapBlazorApp.Server.LLMs.function.Kimi.Parameters;

namespace BootstrapBlazorApp.Server.LLMs.utils;

public class ToolParserUtil
{
   public static List<KimiToolInput> ParseFunction(Type type)
    {
        List<KimiToolInput> inputs = new List<KimiToolInput>();
        
        MethodInfo[] methodInfos = type.GetMethods();
        foreach (MethodInfo methodInfo in methodInfos)
        {
            var attribute = methodInfo.GetCustomAttribute<FunctionDescription>();
            if (attribute == null)
            {
                continue;
            }

            Function function = new Function { Name = methodInfo.Name, Description = attribute.Description };

            var properties = new Dictionary<string, ArgDescription>();
            List<string> required = new List<string>();

            foreach (var parameterInfo in methodInfo.GetParameters())
            {
                var customAttribute = parameterInfo.GetCustomAttribute<FunctionArg>();
                if (customAttribute == null || parameterInfo.Name == null)
                {
                    continue;
                }

                ArgDescription argDescription = new ArgDescription { Description = customAttribute.Description, Type = parameterInfo.ParameterType.Name.ToLower() };
                properties.Add(parameterInfo.Name, argDescription);
                required.Add(parameterInfo.Name);
            }

            function.Parameters = new Parameters { Properties = properties, Required = required };
            inputs.Add(new KimiToolInput { Function = function });
        }
        return inputs;
    }

    public static dynamic? ExecuteKimiFunction(Type type, ReturnMessage returnMessage)
    {
        if (returnMessage.ToolCalls == null)
        {
            return null;
        }
        // 提取第一个工具调用的函数名称和参数
        var toolCall = returnMessage.ToolCalls.First();
        string? functionName = toolCall.Function.Name;
        string? argumentsStr = toolCall.Function.Arguments;
        
        // 检查函数名和参数是否存在
        if (string.IsNullOrEmpty(functionName) || string.IsNullOrEmpty(argumentsStr))
        {
            return null;
        }

        //通过反射获取指定类型方法的信息
        MethodInfo? methodInfo = type.GetMethod(functionName);
        if (methodInfo == null)
        {
            return null;
        }
        var instance = Activator.CreateInstance(type);
        // 获取方法参数信息
        ParameterInfo[] parameterInfos = methodInfo.GetParameters();

        // 解析 JSON 参数字符串为字典
        Dictionary<string, object>? functionArgumentsDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(argumentsStr);

        // 构建参数数组
        object[] parameters = parameterInfos.Select(pi =>
        {
            // 根据参数名查找对应值
            if (functionArgumentsDict != null && functionArgumentsDict.ContainsKey(pi.Name))
            {
                // 尝试转换为相应参数类型
                try
                {
                    return Convert.ChangeType(functionArgumentsDict[pi.Name], pi.ParameterType);
                }
                catch (Exception ex)
                {
                    // 处理转换失败的情况
                    Console.WriteLine($"Error converting argument: {ex.Message}");
                    return null;
                }
            }
            return null;
        }).ToArray();

        // 执行方法并返回结果
        return methodInfo.Invoke(instance, parameters);
    }
}
